﻿
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Windows.UI;

namespace CustomPixelShaderEffect.UlitFolder
{
    public class Hsv : INotifyPropertyChanged
    {
        public Hsv() { }
        public Hsv(double h, double s, double v)
        {
            H = h;
            S = s;
            V = v;
        }

        private double _h;

        /// <summary>
        /// 色相 0~360
        /// </summary>
        public double H
        {
            get { return _h; }
            set
            {
                _h = value;
                OnPropertyChanged();
            }
        }

        private double _s;

        /// <summary>
        /// 亮度 0~100
        /// </summary>
        public double S
        {
            get { return _s; }
            set
            {
                _s = value;
                OnPropertyChanged();
            }
        }

        private double _v;

        /// <summary>
        /// 饱和度 0~100
        /// </summary>
        public double V
        {
            get { return _v; }
            set
            {
                _v = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 将当前hsv转换成颜色返回
        /// </summary>
        public Color HsvToRgb()
        {
            double s = this.S / 100;
            double v = this.V / 100;
            double h = this.H;


            double R = 0, G = 0, B = 0;

            if (s == 0)
                R = G = B = v;
            else
                h /= 60;
            int i = (int)(h);
            double f = h - i;
            double a = v * (1 - s);
            double b = v * (1 - s * f);
            double c = v * (1 - s * (1 - f));


            switch (i)
            {
                case 0:
                case 6:
                    R = v; G = c; B = a;
                    break;
                case 1:
                    R = b; G = v; B = a;
                    break;
                case 2:
                    R = a; G = v; B = c;
                    break;
                case 3:
                    R = a; G = b; B = v;
                    break;
                case 4:
                    R = c; G = a; B = v;
                    break;
                case 5:
                    R = v; G = a; B = b;
                    break;
            }

            R *= 255;
            G *= 255;
            B *= 255;
            Color color = Color.FromArgb(255, (byte)R, (byte)G, (byte)B);

            return color;
        }
        public Hsv RgbToHsv(Color c)
        {
            int R, G, B;
            R = c.R;
            G = c.G;
            B = c.B;

            double V, S, H = 0;

            double max = Math.Max(R, Math.Max(G, B));
            double min = Math.Min(R, Math.Min(G, B));

            var dalte = max - min;

            V = max / 255;

            S = dalte == 0 ? 0 : dalte / max;
            if (R == max) H = (G - B) / (max - min) * 60;
            if (G == max) H = 120 + (B - R) / (max - min) * 60;
            if (B == max) H = 240 + (R - G) / (max - min) * 60;
            if (dalte == 0) H = 0;
            if (H < 0)
                H = H + 360;

            Hsv hsv = new Hsv() { H = (int)H, S = S * 100, V = V * 100 };

            return hsv;
        }
        public static Hsv operator +(Hsv a, Hsv b)
        {
            var h = (a.H + b.H) % 360;
            var s = (a.S + b.S) % 100;
            var v = (a.V + b.V) % 100;
            return new Hsv(h, s, v);
        }
        public Vector3 HsvToVector3()
        {
            var x = (float)(this.H / 360.0);
            var y = (float)(this.S / 100.0);
            var z = (float)(this.V / 100.0);
            return new Vector3(x, y, z);
        }
    }
}
